<style scoped lang="scss">
.image-cropper-container {
  width: 100%;
  height: 100vh;
  background-color: #000;
  color: $color-white;
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
}

.cropper-header {
  width: 100%;
  height: 1.2rem;
  @include flex-space-between-center;
  padding: 0 0.4rem;
  box-sizing: border-box;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);

  .cropper-title {
    font-size: 0.48rem;
    font-weight: 500;
  }

  .cropper-close {
    width: 0.6rem;
    height: 0.6rem;
    @include flex-center;
    font-size: 0.5rem;
    color: $color-white;
    cursor: pointer;

    &:active {
      opacity: 0.7;
    }
  }
}

.cropper-preview {
  width: 100%;
  height: calc(100vh - 1.2rem - 1.5rem);
  @include flex-center;
  position: relative;
  overflow: hidden;

  .cropper-image-wrapper {
    max-width: 100%;
    max-height: 100%;
    position: relative;

    img {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }

    .cropper-box {
      position: absolute;
      border: 2px dashed $color-white;
      box-sizing: border-box;
      width: 6rem;
      height: 6rem;
      z-index: 999;
    }

    .cropper-mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.5);
      mask: radial-gradient(circle, transparent 6rem, black 6rem);
      -webkit-mask: radial-gradient(circle, transparent 6rem, black 6rem);
    }
  }
}

.cropper-footer {
  width: 100%;
  height: 1.5rem;
  @include flex-space-around-center;
  padding: 0 0.6rem;
  box-sizing: border-box;
  border-top: 1px solid rgba(255, 255, 255, 0.1);

  .cropper-btn {
    width: 3.5rem;
    height: 0.9333rem;
    @include flex-center;
    border-radius: 0.4667rem;
    font-size: 0.4267rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s;

    &:active {
      transform: scale(0.98);
    }
  }

  .cropper-btn-cancel {
    background-color: transparent;
    border: 1px solid rgba(255, 255, 255, 0.3);
    color: $color-white;
  }

  .cropper-btn-confirm {
    background-color: $color-white;
    color: $color-black;
    border: none;
  }
}

.cropper-tip {
  position: absolute;
  top: 1.4rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.3467rem;
  color: rgba(255, 255, 255, 0.7);
  padding: 0.2rem 0.4rem;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 0.2rem;
}
</style>
<template>
  <div v-if="isShow" class="image-cropper-container">
    <!-- 头部 -->
    <div class="cropper-header">
      <div class="cropper-title">裁剪图片</div>
      <div class="cropper-close" @click="handleClose">×</div>
    </div>

    <!-- 预览区 -->
    <div class="cropper-preview">
      <div class="cropper-image-wrapper">
        <img ref="imageRef" :src="imageUrl" alt="裁剪图片" />
        <div ref="cropperBoxRef" class="cropper-box"></div> <!-- 裁剪框 -->
        <div ref="cropperMaskRef" class="cropper-mask"></div> <!-- 遮罩 -->
      </div>
      <div class="cropper-tip">拖动调整裁剪区域，双指缩放图片</div>
    </div>

    <!-- 底部按钮 -->
    <div class="cropper-footer">
      <div class="cropper-btn cropper-btn-cancel" @click="handleClose">取消</div>
      <div class="cropper-btn cropper-btn-confirm" @click="handleConfirm">确认裁剪</div>
    </div>
  </div>
</template>
<script setup>
import { onBeforeUnmount } from 'vue';
const props = defineProps({
  imageUrl: {
    type: String,
    default: ''
  },
  isShow: {
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(['close', 'confirm']);

const cropperBoxRef = ref(null);
const imageRef = ref(null);
const cropperMaskRef = ref(null);
let isDragging = false;
let startX = 0;
let startY = 0;
let startTop = 0;
let startLeft = 0;

// 初始化裁剪框位置（居中显示）
const initCropperPosition = () => {
  console.log('qinitCropperPosition执行成功');

  const image = imageRef.value;
  const cropperBox = cropperBoxRef.value;
  const mask = cropperMaskRef.value;
  if (!image || !cropperBox || !mask) return;

  const resetPos = () => {
    const imgWidth = image.offsetWidth;
    const imgHeight = image.offsetHeight;
    const boxWidth = cropperBox.offsetWidth;
    const boxHeight = cropperBox.offsetHeight;

    // 计算居中位置
    const initialLeft = (imgWidth - boxWidth) / 2;
    const initialTop = (imgHeight - boxHeight) / 2;

    // 设置裁剪框位置
    cropperBox.style.left = `${initialLeft}px`;
    cropperBox.style.top = `${initialTop}px`;
    cropperBox.style.transform = 'none';

    // 更新遮罩（跟随裁剪框）
    updateMask(initialLeft, initialTop, boxWidth, boxHeight);
  };

  // 图片加载完成后初始化
  image.complete ? resetPos() : (image.onload = resetPos);
};
const updateMask = (left, top, width, height) => {
  const mask = cropperMaskRef.value;
  if (!mask) return;
  const centerX = left + width / 2;
  const centerY = top + height / 2;
  const radius = width / 2; // 假设是圆形裁剪
  mask.style.mask = `radial-gradient(circle at ${centerX}px ${centerY}px, transparent ${radius}px, black ${radius}px)`;
  mask.style.webkitMask = `radial-gradient(circle at ${centerX}px ${centerY}px, transparent ${radius}px, black ${radius}px)`;
};
// 处理鼠标按下事件（裁剪框拖动）
const handleMouseDown = (e) => {
  console.log('按下鼠标');

  isDragging = true;
  startX = e.touches[0].clientX;
  startY = e.touches[0].clientY;
  const cropperBox = cropperBoxRef.value;
  if (cropperBox) {
    startTop = cropperBox.offsetTop;
    startLeft = cropperBox.offsetLeft;
  }
  e.preventDefault(); // 防止拖动时选中文本
};
// 处理鼠标移动事件（裁剪框拖动）
const handleMouseMove = (e) => {
  if (!isDragging || !cropperBoxRef.value || !imageRef.value) return;

  const cropperBox = cropperBoxRef.value;
  const image = imageRef.value;
  const boxWidth = cropperBox.offsetWidth;
  const boxHeight = cropperBox.offsetHeight;

  // 计算移动距离
  const deltaX = e.touches[0].clientX - startX;
  const deltaY = e.touches[0].clientY - startY;

  // 计算新位置（限制在图片范围内）
  const maxLeft = image.offsetWidth - boxWidth;
  const maxTop = image.offsetHeight - boxHeight;
  const newLeft = Math.max(0, Math.min(startLeft + deltaX, maxLeft));
  const newTop = Math.max(0, Math.min(startTop + deltaY, maxTop));

  // 更新裁剪框位置
  cropperBox.style.left = `${newLeft}px`;
  cropperBox.style.top = `${newTop}px`;

  // 同步更新遮罩
  updateMask(newLeft, newTop, boxWidth, boxHeight);
};
// 处理鼠标松开事件（裁剪框拖动结束）
const handleMouseUp = () => {
  isDragging = false;
};
// 处理确认裁剪事件
const handleConfirm = () => {
  const image = imageRef.value;
  const cropperBox = cropperBoxRef.value;
  if (!image || !cropperBox || !props.imageUrl) return;
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  const boxWidth = cropperBox.offsetWidth;
  const boxHeight = cropperBox.offsetHeight;
  const boxLeft = cropperBox.offsetLeft;
  const boxTop = cropperBox.offsetTop;
  canvas.width = boxWidth;
  canvas.height = boxHeight;
  // 加载原图计算缩放比例（解决图片显示缩放问题）
  const originalImg = new Image(); //新建一个图片对象（专门用来加载原图）
  originalImg.src = props.imageUrl; // 设置原图URL（加载未缩放的原始图片）

  originalImg.onload = () => {
    // 计算显示尺寸与原图尺寸的比例
    const scaleX = originalImg.width / image.offsetWidth; // 原图宽度与显示宽度的比例
    const scaleY = originalImg.height / image.offsetHeight; // 原图高度与显示高度的比例

    // 截取原图对应区域绘制到Canvas
    ctx.drawImage(
      originalImg,
      boxLeft * scaleX, // 原图裁剪起点X
      boxTop * scaleY, // 原图裁剪起点Y
      boxWidth * scaleX, // 原图裁剪宽度
      boxHeight * scaleY, // 原图裁剪高度
      0, 0, // Canvas绘制起点
      boxWidth, boxHeight // Canvas绘制尺寸
    );

    // 转换为图片URL并传出
    const croppedUrl = canvas.toDataURL('image/png');
    emit('confirm', croppedUrl);
    handleClose();
  };
};

// 绑定/解绑拖动事件
const initDragEvents = () => {
  const cropperBox = cropperBoxRef.value;
  if (!cropperBox) return;
  console.log(cropperBox);
  cropperBox.addEventListener('mousedown', handleMouseDown);
  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);

  cropperBox.addEventListener('touchstart', handleMouseDown);
  document.addEventListener('touchmove', handleMouseMove);
  document.addEventListener('touchend', handleMouseUp);
};
// 移除拖动事件
const removeDragEvents = () => {
  const cropperBox = cropperBoxRef.value;
  if (!cropperBox) cropperBox.removeEventListener('touchstart', handleMouseDown);
  document.removeEventListener('touchmove', handleMouseMove);
  document.removeEventListener('touchend', handleMouseUp);
  cropperBox.removeEventListener('mousedown', handleMouseDown);
  document.removeEventListener('mousemove', handleMouseMove);
  document.removeEventListener('mouseup', handleMouseUp);
};

watch(
  () => props.isShow,
  (newVal) => {
    if (newVal) {
      nextTick(() => { // 等待DOM更新后初始化
        initCropperPosition();
        initDragEvents();
      });
    } else {
      removeDragEvents();
    }
  }
);
// 离开组件关闭裁剪组件
const handleClose = () => {
  emit('close', false);
};
onBeforeUnmount(() => {
  emit('close', false);
});
</script>